#pragma once

/**
 * @file market_data_publisher.h
 * @brief 市场数据发布器定义
 * @details 定义了负责将匹配引擎产生的市场数据更新发布到网络的市场数据发布器
 */

#include <functional>

#include "market_data/snapshot_synthesizer.h"

namespace Exchange {
  /**
   * @namespace Exchange
   * @brief 交易所相关功能的命名空间
   */
  /**
   * @class MarketDataPublisher
   * @brief 市场数据发布器类
   * @details 负责从匹配引擎接收市场数据更新，并通过多播发布增量更新和快照数据
   */
  class MarketDataPublisher {
  public:
    /**
     * @brief 构造函数
     * @param market_updates 匹配引擎产生的市场数据更新队列
     * @param iface 网络接口名称
     * @param snapshot_ip 快照数据多播IP地址
     * @param snapshot_port 快照数据多播端口
     * @param incremental_ip 增量数据多播IP地址
     * @param incremental_port 增量数据多播端口
     */
    MarketDataPublisher(MEMarketUpdateLFQueue *market_updates, const std::string &iface,
                        const std::string &snapshot_ip, int snapshot_port,
                        const std::string &incremental_ip, int incremental_port);

    /**
     * @brief 析构函数
     * @details 停止发布线程，等待线程结束，释放快照合成器资源
     */
    ~MarketDataPublisher() {
      stop();

      using namespace std::literals::chrono_literals;
      std::this_thread::sleep_for(5s);

      delete snapshot_synthesizer_;
      snapshot_synthesizer_ = nullptr;
    }

    /**
     * @brief 启动市场数据发布器
     * @details 启动市场数据发布器主线程和内部的快照合成器线程
     */
    auto start() {
      run_ = true;

      ASSERT(Common::createAndStartThread(-1, "Exchange/MarketDataPublisher", [this]() { run(); }) != nullptr, "Failed to start MarketData thread.");

      snapshot_synthesizer_->start();
    }

    /**
     * @brief 停止市场数据发布器
     * @details 停止市场数据发布器主线程和内部的快照合成器线程
     */
    auto stop() -> void {
      run_ = false;

      snapshot_synthesizer_->stop();
    }

    /**
     * @brief 主线程运行函数
     * @details 从匹配引擎的无锁队列中消费市场数据更新，将其发布到增量多播流，并转发给快照合成器
     */
    auto run() noexcept -> void;

    /**
     * @brief 删除的构造函数和赋值运算符
     * @details 禁用默认构造函数、拷贝构造函数、移动构造函数和对应的赋值运算符
     */
    MarketDataPublisher() = delete;

    MarketDataPublisher(const MarketDataPublisher &) = delete;

    MarketDataPublisher(const MarketDataPublisher &&) = delete;

    MarketDataPublisher &operator=(const MarketDataPublisher &) = delete;

    MarketDataPublisher &operator=(const MarketDataPublisher &&) = delete;

  private:
    /**
     * @brief 增量市场数据流的序列号跟踪器
     * @details 用于为每个增量市场数据更新分配唯一的序列号
     */
    size_t next_inc_seq_num_ = 1;

    /**
     * @brief 匹配引擎发送的市场数据更新的无锁队列
     * @details 从该队列中消费匹配引擎产生的市场数据更新
     */
    MEMarketUpdateLFQueue *outgoing_md_updates_ = nullptr;

    /**
     * @brief 转发给快照合成器的增量市场数据更新的无锁队列
     * @details 用于将增量市场数据更新转发给快照合成器
     */
    MDPMarketUpdateLFQueue snapshot_md_updates_;

    volatile bool run_ = false; /**< 线程运行标志 */

    std::string time_str_; /**< 时间字符串缓存，用于日志记录 */
    Logger logger_; /**< 日志记录器 */

    /**
     * @brief 增量市场数据流的多播套接字
     * @details 用于发布增量市场数据更新
     */
    Common::McastSocket incremental_socket_;

    /**
     * @brief 快照合成器
     * @details 用于合成和发布限价订单簿快照到快照多播流
     */
    SnapshotSynthesizer *snapshot_synthesizer_ = nullptr;
  };
}
